home *** CD-ROM | disk | FTP | other *** search
- global NUM_ROWS, NUM_COLS, NUM_SQUARES, THE_TEMPO, gpvPossibleMovesList, gpvMainBoard, gopvDrawBoards, MIN_COMPUTER_PLAY_TIME, MAX_COMPUTER_LOOK_AHEAD, DEFINITIVE_SQUARE_MULT, INTERIOR_SQUARE_MULT, UNDEF_VALUE, gpvComputerPlayer, gpvEarliestComputerDecide, gpvComputerMove, gpvComputerScores, gpvComputerMoves, gpvComputerMoveIndex, gpvCompBoards, gpvCompPlayerNum, gopvNextResetLevel, gpvBoardValues, gopvBestScore, gopvBestMoves, gpvBestWorstFlags, gpvThrowGame
-
- on gopvSetComputerDifficulty computerDiff, numLevel
- gpvThrowGame = 0
- if computerDiff = #easy then
- MAX_COMPUTER_LOOK_AHEAD = 2
- gpvThrowGame = 1
- else
- if computerDiff = #medium then
- MAX_COMPUTER_LOOK_AHEAD = 1
- else
- if computerDiff = #hard then
- MAX_COMPUTER_LOOK_AHEAD = 2
- else
- if computerDiff = #harder then
- MAX_COMPUTER_LOOK_AHEAD = 3
- else
- if computerDiff = #hardest then
- MAX_COMPUTER_LOOK_AHEAD = 4
- else
- alert("Error. computerDiff value" && computerDiff && "is unacceptable")
- end if
- end if
- end if
- end if
- end if
- end
-
- on goSetMinComputerTime numTicks
- MIN_COMPUTER_PLAY_TIME = numTicks
- end
-
- on gopvInitComputerPlayer computerDiff, numLevel
- MIN_COMPUTER_PLAY_TIME = 5
- THE_TEMPO = 20
- DEFINITIVE_SQUARE_MULT = 8
- INTERIOR_SQUARE_MULT = 3
- UNDEF_VALUE = 1000000
- gopvSetComputerDifficulty(computerDiff, numLevel)
- gopvDrawBoards = 0
- gpvBoardValues = []
- repeat with i = 1 to NUM_SQUARES
- gpvBoardValues[i] = 0
- end repeat
- gopvInitBoards()
- end
-
- on goStartComputerMove playerNum
- gpvComputerPlayer = playerNum
- gpvEarliestComputerDecide = the timer + MIN_COMPUTER_PLAY_TIME
- gpvComputerMove = 0
- gopvNextResetLevel = 0
- gpvComputerMoves = []
- gpvComputerScores = []
- gpvComputerMoveIndex = []
- gpvCompBoards = []
- gpvCompPlayerNum = []
- gpvBestWorstFlags = []
- repeat with i = 1 to MAX_COMPUTER_LOOK_AHEAD
- if (i mod 2) = 1 then
- pnum = gpvComputerPlayer
- else
- pnum = 3 - gpvComputerPlayer
- end if
- append(gpvComputerMoves, [])
- append(gpvComputerScores, [])
- append(gpvCompBoards, [])
- gopvInitBoard(gpvCompBoards[i])
- append(gpvComputerMoveIndex, -1)
- append(gpvCompPlayerNum, pnum)
- append(gpvBestWorstFlags, (i = 1) and (gpvThrowGame = 0))
- end repeat
- end
-
- on gopvMakeNewBoard theCurBoard, theNewBoard, playerNum, pieceNum, drawBoard
- gopvCopyBoard(theCurBoard, theNewBoard)
- if pieceNum <> -1 then
- gopvAssignBoard(theNewBoard, pieceNum, playerNum)
- gopvTransitionBoardEx(theNewBoard, pieceNum)
- end if
- if drawBoard then
- gopvDrawBoard(theNewBoard, pieceNum)
- end if
- end
-
- on gopvGetNextLevelToDefine
- curLevel = -1
- numPasses = 0
- repeat with i = 1 to MAX_COMPUTER_LOOK_AHEAD
- if gpvComputerMoveIndex[i] = -1 then
- curLevel = i
- exit repeat
- next repeat
- end if
- theMove = gpvComputerMoves[i][gpvComputerMoveIndex[i]]
- if theMove = -1 then
- numPasses = numPasses + 1
- if numPasses = 2 then
- exit repeat
- end if
- next repeat
- end if
- numPasses = 0
- end repeat
- return curLevel
- end
-
- on drawPathAndScore n, markNum, count1, count2, theScore
- pathStr = EMPTY
- repeat with i = 1 to n
- moveIndex = gpvComputerMoveIndex[i]
- if i = markNum then
- pathStr = pathStr & "*" & moveIndex
- next repeat
- end if
- pathStr = pathStr && moveIndex
- end repeat
- end
-
- on gopvGetBoardValues theBoard
- repeat with i = 1 to NUM_SQUARES
- if theBoard[i] = 0 then
- gpvBoardValues[i] = 0
- next repeat
- end if
- gpvBoardValues[i] = (2 * theBoard[i]) - 3
- end repeat
- numChanges = 1
- repeat while numChanges > 0
- numChanges = 0
- repeat with row = 1 to NUM_ROWS
- repeat with col = 1 to NUM_COLS
- n = gopvRowColToNum(row, col)
- theValue = gpvBoardValues[n]
- if abs(theValue) = 1 then
- defVert = 0
- defHorz = 0
- defDiag1 = 0
- defDiag2 = 0
- if row = 1 then
- defVert = 1
- else
- if gpvBoardValues[n - NUM_COLS] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defVert = 1
- end if
- end if
- if row = NUM_ROWS then
- defVert = 1
- else
- if gpvBoardValues[n + NUM_COLS] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defVert = 1
- end if
- end if
- if col = 1 then
- defHorz = 1
- else
- if gpvBoardValues[n - 1] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defHorz = 1
- end if
- end if
- if col = NUM_COLS then
- defHorz = 1
- else
- if gpvBoardValues[n + 1] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defHorz = 1
- end if
- end if
- if (row = 1) or (col = 1) then
- defDiag1 = 1
- else
- if gpvBoardValues[n - NUM_COLS - 1] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defDiag1 = 1
- end if
- end if
- if (row = NUM_ROWS) or (col = NUM_COLS) then
- defDiag1 = 1
- else
- if gpvBoardValues[n + NUM_COLS + 1] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defDiag1 = 1
- end if
- end if
- if (row = 1) or (col = NUM_COLS) then
- defDiag2 = 1
- else
- if gpvBoardValues[n - NUM_COLS + 1] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defDiag2 = 1
- end if
- end if
- if (row = NUM_ROWS) or (col = 1) then
- defDiag2 = 1
- else
- if gpvBoardValues[n + NUM_COLS - 1] = (theValue * DEFINITIVE_SQUARE_MULT) then
- defDiag2 = 1
- end if
- end if
- if defVert and defHorz and defDiag1 and defDiag2 then
- gpvBoardValues[n] = gpvBoardValues[n] * DEFINITIVE_SQUARE_MULT
- numChanges = numChanges + 1
- end if
- end if
- end repeat
- end repeat
- end repeat
- n = gopvRowColToNum(1, 1)
- gpvBoardValues[n] = 2 * gpvBoardValues[n]
- n = gopvRowColToNum(NUM_ROWS, 1)
- gpvBoardValues[n] = 2 * gpvBoardValues[n]
- n = gopvRowColToNum(1, NUM_COLS)
- gpvBoardValues[n] = 2 * gpvBoardValues[n]
- n = gopvRowColToNum(NUM_ROWS, NUM_COLS)
- gpvBoardValues[n] = 2 * gpvBoardValues[n]
- end
-
- on gopvCheckPrune theLevel, leafNode
- if theLevel > 1 then
- doPrune = 0
- theMoveIndex = gpvComputerMoveIndex[theLevel]
- theScore = gpvComputerScores[theLevel][theMoveIndex]
- if gpvBestWorstFlags[theLevel] = 1 then
- betaValue = gpvComputerScores[theLevel - 1].min()
- if theScore > betaValue then
- doPrune = 1
- end if
- else
- alphaValue = gpvComputerScores[theLevel - 1].max()
- if theScore < alphaValue then
- doPrune = 1
- end if
- end if
- if doPrune then
- if leafNode = 0 then
- xxxxxx = 1
- end if
- gpvComputerMoveIndex[theLevel] = gpvComputerMoves[theLevel].count()
- repeat with i = theLevel + 1 to MAX_COMPUTER_LOOK_AHEAD
- gpvComputerMoveIndex[i] = -1
- gpvComputerMoves[i] = []
- end repeat
- end if
- end if
- end
-
- on gopvGetPathAndScore playerNum, drawResults
- repeat with i = 1 to MAX_COMPUTER_LOOK_AHEAD
- moveIndex = gpvComputerMoveIndex[i]
- if moveIndex = -1 then
- n = i - 1
- exit repeat
- end if
- n = i
- end repeat
- theCounts = [0, 0]
- theBoard = gpvCompBoards[n]
- gopvGetBoardValues(theBoard)
- repeat with i = 1 to NUM_SQUARES
- pieceNum = theBoard[i]
- if pieceNum > 0 then
- theCounts[pieceNum] = theCounts[pieceNum] + abs(gpvBoardValues[i])
- end if
- end repeat
- if playerNum = 1 then
- theScore = theCounts[1] - theCounts[2]
- else
- theScore = theCounts[2] - theCounts[1]
- end if
- gpvComputerScores[n][gpvComputerMoveIndex[n]] = theScore
- gopvCheckPrune(n, 1)
- if gopvDrawBoards then
- drawPathAndScore(n, gopvNextResetLevel, theCounts[1], theCounts[2], theScore)
- repeat with i = n down to 1
- end repeat
- end if
- end
-
- on gopvRecurseOneMove
- curLevel = gopvGetNextLevelToDefine()
- repeat while curLevel <> -1
- gpvComputerMoves[curLevel] = []
- gpvComputerScores[curLevel] = []
- if curLevel = 1 then
- theCurBoard = gpvMainBoard
- else
- theCurBoard = gpvCompBoards[curLevel - 1]
- end if
- numMoves = gopvNewNumPossibleMoves(gpvCompPlayerNum[curLevel], theCurBoard, gpvComputerMoves[curLevel])
- if gpvBestWorstFlags[curLevel] = 1 then
- defScore = -UNDEF_VALUE
- else
- defScore = UNDEF_VALUE
- end if
- if numMoves = 0 then
- append(gpvComputerMoves[curLevel], -1)
- append(gpvComputerScores[curLevel], defScore)
- else
- repeat with i = 1 to numMoves
- append(gpvComputerScores[curLevel], defScore)
- end repeat
- end if
- gpvComputerMoveIndex[curLevel] = 1
- if gopvDrawBoards then
- put "Level" && curLevel && "Defined for Player" && gpvCompPlayerNum[curLevel] && ": " && gpvComputerMoves[curLevel]
- end if
- theMove = gpvComputerMoves[curLevel][1]
- gopvMakeNewBoard(theCurBoard, gpvCompBoards[curLevel], gpvCompPlayerNum[curLevel], theMove, gopvDrawBoards)
- curLevel = gopvGetNextLevelToDefine()
- end repeat
- gopvGetPathAndScore(gpvCompPlayerNum[1], 1)
- end
-
- on gopvChooseScore curLevel, scoresList
- perspectivePlayerNum = gpvCompPlayerNum[1]
- thisPlayerNum = gpvCompPlayerNum[curLevel]
- if thisPlayerNum = perspectivePlayerNum then
- theScore = scoresList.max()
- else
- theScore = scoresList.min()
- end if
- return theScore
- end
-
- on gopvNextMove
- if gopvDrawBoards then
- put "*********** Finding next Move ***********"
- end if
- retcode = 0
- repeat with i = MAX_COMPUTER_LOOK_AHEAD down to 0
- if gpvComputerMoveIndex[i] <> -1 then
- curLevel = i
- exit repeat
- end if
- end repeat
- repeat while (curLevel > 0) and (retcode = 0)
- moveIndex = gpvComputerMoveIndex[curLevel] + 1
- if moveIndex <= count(gpvComputerMoves[curLevel]) then
- gpvComputerMoveIndex[curLevel] = moveIndex
- theMove = gpvComputerMoves[curLevel][moveIndex]
- if curLevel = 1 then
- theCurBoard = gpvMainBoard
- else
- theCurBoard = gpvCompBoards[curLevel - 1]
- end if
- if gopvDrawBoards then
- put "NextMove is at Level" && curLevel && ", Index" && moveIndex && ", Move" && theMove
- end if
- gopvMakeNewBoard(theCurBoard, gpvCompBoards[curLevel], gpvCompPlayerNum[curLevel], theMove, gopvDrawBoards)
- gopvNextResetLevel = curLevel
- retcode = 1
- next repeat
- end if
- if gopvDrawBoards then
- put "No more Moves at Level" && curLevel && "so reseting to undefined and backing up"
- end if
- if curLevel > 1 then
- if gpvBestWorstFlags[curLevel] = 1 then
- chosenScore = gpvComputerScores[curLevel].max()
- else
- chosenScore = gpvComputerScores[curLevel].min()
- end if
- curMoveIndex = gpvComputerMoveIndex[curLevel - 1]
- gpvComputerScores[curLevel - 1][curMoveIndex] = chosenScore
- gopvCheckPrune(curLevel - 1, 0)
- end if
- gpvComputerMoveIndex[curLevel] = -1
- curLevel = curLevel - 1
- end repeat
- return retcode
- end
-
- on gopvNewBestMove
- gopvBestMoves = []
- if gpvThrowGame = 0 then
- gopvBestScore = -UNDEF_VALUE
- else
- gopvBestScore = UNDEF_VALUE
- end if
- theMoveList = gpvComputerMoves[1]
- theScoreList = gpvComputerScores[1]
- n = count(theScoreList)
- repeat with i = 1 to n
- theMove = theMoveList[i]
- theScore = theScoreList[i]
- if theScore = gopvBestScore then
- append(gopvBestMoves, theMove)
- next repeat
- end if
- if gpvThrowGame = 0 then
- if theScore > gopvBestScore then
- gopvBestScore = theScore
- gopvBestMoves = [theMove]
- end if
- next repeat
- end if
- if theScore < gopvBestScore then
- gopvBestScore = theScore
- gopvBestMoves = [theMove]
- end if
- end repeat
- end
-
- on gopvRecurseComputerMoves timeToQuit
- moreMoves = 1
- repeat while (moreMoves = 1) and (the timer <= timeToQuit)
- gopvRecurseOneMove()
- moreMoves = gopvNextMove()
- end repeat
- theMove = 0
- if moreMoves = 0 then
- gopvNewBestMove()
- numMoves = count(gopvBestMoves)
- if numMoves > 0 then
- whichMove = random(count(gopvBestMoves))
- theMove = gopvBestMoves[whichMove]
- else
- theMove = -1
- end if
- end if
- return theMove
- end
-
- on goContinueComputerMove
- if gpvComputerMove = 0 then
- gpvComputerMove = gopvRecurseComputerMoves(the timer + (60 / THE_TEMPO))
- end if
- if the timer >= gpvEarliestComputerDecide then
- retcode = gpvComputerMove
- else
- retcode = 0
- end if
- return retcode
- end
-